package il.co.gadiworks.mrnom;

import java.util.List;

import android.graphics.Color;

import il.co.gadiworks.mrnom.framework.Game;
import il.co.gadiworks.mrnom.framework.Graphics;
import il.co.gadiworks.mrnom.framework.Input.TouchEvent;
import il.co.gadiworks.mrnom.framework.Pixmap;
import il.co.gadiworks.mrnom.framework.Screen;

public class GameScreen extends Screen {
	enum GameState {
		Ready,
		Running,
		Paused,
		GameOver
	}
	
	GameState state = GameState.Ready;
	World world;
	int oldScore = 0;
	String score = "0";
	
	public GameScreen(Game game) {
		super(game);
		this.world = new World();
	}

	@Override
	public void update(float deltaTime) {
		List<TouchEvent> touchEvents = GAME.getInput().getTouchEvents();
		GAME.getInput().getKeyEvents();
		
		if (this.state == GameState.Ready) {
			updateReady(touchEvents);
		}
		else if (this.state == GameState.Running) {
			updateRunning(touchEvents, deltaTime);
		}
		else if (this.state == GameState.Paused) {
			updatePaused(touchEvents);
		}
		else if (this.state == GameState.GameOver) {
			updateGameOver(touchEvents);
		}
	}

	private void updateGameOver(List<TouchEvent> touchEvents) {
		int len = touchEvents.size();
		for (int i = 0; i < len; i++) {
			TouchEvent event = touchEvents.get(i);
			if (event.type == TouchEvent.TOUCH_UP) {
				if (event.x >= 128 && event.x <= 192 &&
					event.y >= 200 && event.y <= 264) {
					if (Settings.soundEnabled) {
						Assets.click.play(1);
					}
					GAME.setScreen(new MainMenuScreen(GAME));
					return;
				}
			}
		}
	}

	private void updatePaused(List<TouchEvent> touchEvents) {
		int len = touchEvents.size();
		for (int i = 0; i < len; i++) {
			TouchEvent event = touchEvents.get(i);
			if (event.type == TouchEvent.TOUCH_UP) {
				if (event.x > 80 && event.x <= 240) {
					if (event.y > 100 && event.y <= 148) {
						if (Settings.soundEnabled) {
							Assets.click.play(1);
						}
						this.state = GameState.Running;
						return;
					}
					if (event.y > 148 && event.y < 196) {
						if (Settings.soundEnabled) {
							Assets.click.play(1);
						}
						GAME.setScreen(new MainMenuScreen(GAME));
						return;
					}
				}
			}
		}
	}

	private void updateRunning(List<TouchEvent> touchEvents, float deltaTime) {
		int len = touchEvents.size();
		for (int i = 0; i < len; i++) {
			TouchEvent event = touchEvents.get(i);
			if (event.type == TouchEvent.TOUCH_UP) {
				if (event.x < 64 && event.y < 64) {
					if (Settings.soundEnabled) {
						Assets.click.play(1);
					}
					this.state = GameState.Paused;
					return;
				}
			}
			if (event.type == TouchEvent.TOUCH_DOWN) {
				if (event.x < 64 && event.y > 416) {
					this.world.snake.turnLeft();
				}
				if (event.x > 256 && event.y > 416) {
					this.world.snake.turnRight();
				}
			}
		}
		
		this.world.update(deltaTime);
		if (this.world.gameOver) {
			if (Settings.soundEnabled) {
				Assets.bitten.play(1);
			}
			this.state = GameState.GameOver;
		}
		
		if (this.oldScore != this.world.score) {
			this.oldScore = this.world.score;
			this.score = "" + this.oldScore;
			
			if (Settings.soundEnabled) {
				Assets.eat.play(1);
			}
		}
	}

	private void updateReady(List<TouchEvent> touchEvents) {
		if (touchEvents.size() > 0) {
			this.state = GameState.Running;
		}
	}

	@Override
	public void present(float deltaTime) {
		Graphics g = GAME.getGraphics();
		
		g.drawPixmap(Assets.background, 0, 0);
		drawWorld(this.world);
		
		if (this.state == GameState.Ready) {
			drawReadyUI();
		}
		else if (this.state == GameState.Running) {
			drawRunningUI();
		}
		else if (this.state == GameState.Paused) {
			drawPausedUI();
		}
		else if (this.state == GameState.GameOver) {
			drawGameOverUI();
		}
		
		drawText(g, this.score, g.getWidth() / 2 - this.score.length() * 20 / 2, g.getHeight() - 42);
	}

	private void drawText(Graphics g, String line, int x, int y) {
		int len = line.length();
		for (int i = 0; i < len; i++) {
			char character = line.charAt(i);
			
			if (character == ' ') {
				x += 20;
				continue;
			}
			
			int srcX = 0;
			int srcWidth = 0;
			
			if (character == '.') {
				srcX = 200;
				srcWidth = 10;
			}
			else {
				srcX = (character - '0') * 20;
				srcWidth = 20;
			}
			
			g.drawPixmap(Assets.numbers, x, y, srcX, 0, srcWidth, 32);
			x += srcWidth;
		}
	}

	private void drawGameOverUI() {
		Graphics g = GAME.getGraphics();
		
		g.drawPixmap(Assets.gameOver, 62, 100);
		g.drawPixmap(Assets.buttons, 128, 200, 0, 128, 64, 64);
		g.drawLine(0, 416, 480, 416, Color.BLACK);
	}

	private void drawPausedUI() {
		Graphics g = GAME.getGraphics();
		
		g.drawPixmap(Assets.pause, 80, 100);
		g.drawLine(0, 416, 480, 416, Color.BLACK);
	}

	private void drawRunningUI() {
		Graphics g = GAME.getGraphics();
		
		g.drawPixmap(Assets.buttons, 0, 0, 64, 128, 64, 64);
		g.drawLine(0, 416, 480, 416, Color.BLACK);
		g.drawPixmap(Assets.buttons, 0, 416, 64, 64, 64, 64);
		g.drawPixmap(Assets.buttons, 256, 416, 0, 64, 64, 64);
	}

	private void drawReadyUI() {
		Graphics g = GAME.getGraphics();
		
		g.drawPixmap(Assets.ready, 47, 100);
		g.drawLine(0, 416, 480, 416, Color.BLACK);
	}

	private void drawWorld(World world) {
		Graphics g = GAME.getGraphics();
		
		Snake snake = world.snake;
		SnakePart head = snake.parts.get(0);
		Stain stain = world.stain;
		
		Pixmap stainPixmap = null;
		
		if (stain.type == Stain.TYPE_1) {
			stainPixmap = Assets.stain1;
		}
		else if (stain.type == Stain.TYPE_2) {
			stainPixmap = Assets.stain2;
		}
		else if (stain.type == Stain.TYPE_3) {
			stainPixmap = Assets.stain3;
		}
		
		int x = stain.x * 32;
		int y = stain.y * 32;
		
		g.drawPixmap(stainPixmap, x, y);
		
		int len = snake.parts.size();
		for (int i = 1; i < len; i++) {
			SnakePart part = snake.parts.get(i);
			x = part.x * 32;
			y = part.y * 32;
			g.drawPixmap(Assets.tail, x, y);
		}
		
		Pixmap headPixmap = null;
		if (snake.direction == Snake.UP) {
			headPixmap = Assets.headUp;
		}
		else if (snake.direction == Snake.LEFT) {
			headPixmap = Assets.headLeft;
		}
		else if (snake.direction == Snake.DOWN) {
			headPixmap = Assets.headDown;
		}
		else if (snake.direction == Snake.RIGHT) {
			headPixmap = Assets.headRight;
		}
		
		x = head.x * 32 + 16;
		y = head.y * 32 + 16;
		g.drawPixmap(headPixmap, x - headPixmap.getWidth() / 2, y - headPixmap.getHeight() / 2);
	}
	

	@Override
	public void pause() {
		if (this.state == GameState.Running) {
			this.state = GameState.Paused;
		}
		
		if (this.world.gameOver) {
			Settings.addScore(this.world.score);
			Settings.save(GAME.getFileIO());
		}
	}

	@Override
	public void resume() {

	}

	@Override
	public void dispose() {

	}
}